package com.lagou.homework.annotation;

import java.lang.annotation.Annotation;
import java.util.*;

/**
 * @author boting.guo
 * @date 2021/9/19 3:36
 */

public class AnnotationsScanner {

	private final static String[] annotationFilterPrefixes = {"java.lang.", "org.springframework.lang."};

	private static final Map<String, Annotation[]> declaredAnnotationCache = new HashMap<>(256);


	// 获取指定类上的直接注解
	public static Annotation[] getDeclaredAnnotations(Class<?> source) {
		String sourceName = source.getName();
		Annotation[] annotations = declaredAnnotationCache.get(sourceName);
		if (annotations != null) {
			return annotations.clone();
		} else {
			annotations = source.getDeclaredAnnotations();
			if (annotations.length != 0) {
				boolean allIgnored = true;
				for (int i = 0; i < annotations.length; i++) {
					Annotation annotation = annotations[i];
					if (isIgnorable(annotation.annotationType())) {
						annotations[i] = null;
					} else {
						allIgnored = false;
					}
				}

				annotations = allIgnored ? new Annotation[0] : annotations;
				declaredAnnotationCache.put(sourceName, annotations);
			}
		}
		return annotations.clone();
	}

	// 递归获取指定类上的所有注解(包括间接注解)
	public static List<Annotation> getMergedAnnotations(Class<?> source) {
		List<Annotation> annotations = new ArrayList<>(64);
		Annotation[] declaredAnnotations = getDeclaredAnnotations(source);
			for (Annotation annotation : declaredAnnotations) {
				if (annotation != null) {
					annotations.add(annotation);
					annotations.addAll(getMergedAnnotations(annotation.annotationType()));
				}
			}
		return annotations;
	}

	private static boolean isIgnorable(Class<?> annotationType) {
		String type = annotationType.getName();
		for (String prefix: annotationFilterPrefixes) {
			if(type.startsWith(prefix)) {
				return true;
			}
		}
		return false;
	}
}
